﻿using MyNetwork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VFTray
{
	class ComServer
	{
		#region normal_parts
		internal ServerSocketTcp server = new ServerSocketTcp();

        internal void Init()
        {
            var cfg = GlobalParams.CD.ComServer;
            if (cfg.Enabled == false)
            {
                LogUtility.LOG.Info("ComServer START Disabled " + server.IP + ":" + server.Port.ToString());
                return;
            }
            LogUtility.LOG.Info("ComServer START " + server.IP + ":" + server.Port.ToString());
            server.IP = cfg.IP;
            server.Port = cfg.Port;
            server.Capability = cfg.Capability;
            server.Accepted += Server_Accepted;
            server.Start();

        }

        internal void Close()
        {
            LogUtility.LOG.Info("ComServer CLOSED " + server.IP + ":" + server.Port.ToString());

            server.Accepted -= Server_Accepted;
            server.Close();
        }

        ClientSocketTcp client = null;
		private void Server_Accepted(ClientSocketTcp obj)
		{
			client = obj;
			LogUtility.LOG.Info(client.Key + " Accepted");
			client.Received += Client_Received;
			client.Closed += Client_Closed;
		}
        #endregion normal_parts

        internal RVStatus rvEcho = new RVStatus("ECHO");
        internal RVStatus rvFeed = new RVStatus("Feed");
        //site:站点号 0,1,2,3
        
        internal RVStatus rvBin = new RVStatus("Bin");
        //site:站点号 0,1,2,3

        internal RVStatus rvSnap = new RVStatus("Snap");
        //site:站点号 0,1,2,3
        //identity:标识号0,1

        internal RVStatus rvAllInOne = new RVStatus("AllInOne");
        //site:站点号 0,1,2,3
        //identity:标识号0,1
        //count
        //全过程
        
        internal RVStatus rvConfig = new RVStatus("Config");
        //paramname = paramvalue

        internal RVStatus rvClearCV = new RVStatus("ClearCV");

        private bool CheckIndexFeeder(RVStatus rv)
        {
            if(rv.SiteID < 0 || rv.SiteID >= GlobalParams.CD.Trayes.Count)
            {
                string emsg = "站号超出[0," + (GlobalParams.CD.Trayes.Count - 1).ToString() + "]";
                SendRv(emsg, rv);
                return false;
            }

            if (GlobalParams.PC.Feeders[rv.SiteID].GetCfgFeed().Enabled == false ||
                   GlobalParams.PC.Feeders[rv.SiteID].Connected == false)
            {
                SendRv("震动盘未连接", rv);
                return false;
            }
            index_feeder = rv.SiteID;

            return true;
        }
        private bool CheckMarkID(RVStatus rv)
        {
            int idx = rv.MarkID1;
            if (idx < 0 || idx > 1)
            {
                SendRv("标识号1错误", rv);
                return false;
            }
            mark1_req1 = idx;
            idx = rv.MarkID2;
            if (idx < 0 || idx > 1)
            {
                SendRv("标识号2错误", rv);
                return false;
            }

            mark1_req2 = idx;
            identity_req = idx;
            return true;
        }
        private bool CheckCount(RVStatus rv)
        {
            if (rv.Count1 < 0)
            {
                SendRv("需求个数1错误", rv);
                return false;
            }
            if (rv.Count2 < 0)
            {
                SendRv("需求个数1错误", rv);
                return false;
            }

            count_req1 = rv.Count1;
            count_req2 = rv.Count2;
            return true;
        }
        private void Client_Received(string obj)
		{
            if (GlobalParams.PC.Status_Verified.LO) return;
            //GlobalParams.MF.wndRV.AddMsg(obj);
            RVStatus rvRtn = new RVStatus("TEST");
            if (rvRtn.Parse(obj) == false) return;
            if (rvRtn.Command == rvEcho.Command)
            {
                Send(rvRtn.NewCommand());
            }
            else if (rvRtn.Command == rvFeed.Command)
            {
                LogUtility.LOG.Debug("RECV " + rvRtn.CMD);

                if (!CheckIndexFeeder(rvRtn))
                {
                    return;
                }

                GlobalParams.MF.wndRun.AddMessage(index_feeder, "RECV:" + rvRtn.CMD);

                var feed = GlobalParams.PC.Feeders[index_feeder];

                if (rvRtn.Content.Contains("CHECKCOUNT"))
                {
                    var list1 = feed.CV.GetRemains(0);
                    var list2 = feed.CV.GetRemains(1);

                    if (rvRtn.Count1 > 0)
                    {
                        if (list1.Count > rvRtn.Count1)
                        {
                            if (rvRtn.Count2 > 0)
                            {
                                if (list2.Count > rvRtn.Count2)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                }

                feed.Resp = rvRtn.Clone();
                feed.ShakeNeedResp = true;
                feed.BiningNeedResp = false;
                feed.AllInOne = false;
                feed.CountShake = 0;
                feed.CountBin = 0;
                feed.Index_Mark1 = 0;
                feed.Index_Mark2 = 0;
                feed.CountRequired1 = 0;
                feed.CountRequired2 = 0;
                if (feed.StartShakeing() == false)
                {
                    SendRv(feed.StatusMessage, rvRtn);
                }
            }
            else if (rvRtn.Command == rvBin.Command)
            {
                LogUtility.LOG.Debug("RECV " + rvRtn.CMD);

                if (!CheckIndexFeeder(rvRtn))
                {
                    return;
                }

                GlobalParams.MF.wndRun.AddMessage(index_feeder, "RECV:" + rvBin.Content);
                var feed = GlobalParams.PC.Feeders[index_feeder];
                feed.Resp = rvRtn.Clone();
                feed.ShakeNeedResp = false;
                feed.BiningNeedResp = true;
                feed.AllInOne = false;
                feed.CountShake = 0;
                feed.CountBin = 0;
                feed.Index_Mark1 = 0;
                feed.Index_Mark2 = 0;
                feed.CountRequired1 = 0;
                feed.CountRequired2 = 0;
                if (feed.StartBining() == false)
                {
                    SendRv(feed.StatusMessage, rvBin);
                }
            }
            else if (rvRtn.Command == rvSnap.Command)
            {
                LogUtility.LOG.Debug("RECV " + rvRtn.CMD);

                if (!CheckIndexFeeder(rvRtn)) return;
                if (!CheckMarkID(rvRtn)) return;

                if (!CheckCount(rvRtn)) return;


                GlobalParams.MF.wndRun.AddMessage(index_feeder, "RECV:" + rvRtn.CMD);

                var feed = GlobalParams.PC.Feeders[index_feeder];
                feed.Resp = rvRtn.Clone();
                feed.ShakeNeedResp = false;
                feed.BiningNeedResp = false;
                feed.AllInOne = false;
                feed.CountShake = 0;
                feed.CountBin = 0;
                feed.Index_Mark1 = mark1_req1;
                feed.CountRequired1 = count_req1;
                feed.Index_Mark2 = mark1_req2;
                feed.CountRequired2 = count_req2;

                if (feed.StartSnapping(true) == false)
                {
                    SendRv(feed.StatusMessage, rvRtn);
                }
            }
            else if (rvRtn.Command == rvAllInOne.Command)//snap shake bin: allinone
            {
                LogUtility.LOG.Debug("RECV " + rvRtn.CMD);


                if (!CheckIndexFeeder(rvRtn)) return;
                if (!CheckMarkID(rvRtn)) return;

                if (!CheckCount(rvRtn)) return;

                GlobalParams.MF.wndRun.AddMessage(index_feeder, "RECV:" + rvRtn.CMD);

                var feed = GlobalParams.PC.Feeders[index_feeder];
                feed.Resp = rvRtn.Clone();

                feed.ShakeNeedResp = false;
                feed.BiningNeedResp = false;
                feed.AllInOne = true;
                feed.CountShake = 0;
                feed.CountBin = 0;
                feed.Index_Mark1 = mark1_req1;
                feed.CountRequired1 = count_req1;
                feed.Index_Mark2 = mark1_req2;
                feed.CountRequired2 = count_req2;
                if (feed.StartSnapping(feed.GetStep().req_mode == 0) == false)
                {
                    SendRv(feed.StatusMessage, rvRtn);
                }
            }
            else if (rvRtn.Command == rvConfig.Command)
            {
                LogUtility.LOG.Debug("RECV " + rvRtn.CMD);

                if (string.IsNullOrEmpty(rvRtn.Content))
                {
                    SendRv("Format Error", rvRtn);
                    return;
                }

                if (!CheckIndexFeeder(rvRtn)) return;

                parseConfig(rvRtn);
            }
            else if (rvRtn.Command == rvClearCV.Command)
            {
                LogUtility.LOG.Debug("RECV " + rvRtn.CMD);

                //if (string.IsNullOrEmpty(rvRtn.Content))
                //{
                //    SendRv("Format Error", rvRtn);
                //    return;
                //}

                if (!CheckIndexFeeder(rvRtn)) return;

                try
                {
                    var feed = GlobalParams.PC.Feeders[index_feeder];
                    feed.CV.Clear();
                    SendRv("OK", rvRtn);
                }
                catch (Exception ex)
                {
                    LogUtility.LOG.Error("ERROR ClearCV CMD", ex);
                }
            }
        }

        private void parseConfig(RVStatus rvRtn)
		{
            var feed = GlobalParams.PC.Feeders[index_feeder];
            var content = rvRtn.Content;
            if (string.IsNullOrEmpty(content))
            {
                SendRv("Format is not correct", rvConfig);
                return;
            }
            var ps = content.Split(new char[] { '=' });
            if(ps.Length<2)
			{
                SendRv("Format is not correct", rvConfig);
                return;
            }

            if(string.IsNullOrEmpty(ps[0])||string.IsNullOrEmpty(ps[1]))
            {
                SendRv("Format is not correct", rvConfig);
                return;
            }
            if (ps[0] == "Recipe")
            {
                Task.Run(() =>
                {
                    if (GlobalParams.PC.UpdateRecipe(ps[1]))
                    {
                        Send(rvConfig.RespCommand("OK"));
                    }
                    else
                    {
                        Send(rvConfig.RespCommand("NG"));
                    }
                });
            }
            else if (ps[0] == "Axes")
            {
                if (string.IsNullOrEmpty(ps[1]))
                {
                }
                else
                {
                    var sa = ps[1].Split(new char[] { ',' });
                    float x = 0;
                    float y = 0;
                    if (float.TryParse(sa[0], out x) && float.TryParse(sa[1], out y))
                    {
                        GlobalParams.MF.wndCfgV.NotifyAxes(index_feeder, x, y);
                    }
                }
            }
            else
            {
                SendRv("NO SUPPORT", rvConfig);
            }
        }

		int index_feeder =0;
        int identity_req = 0;
        int mark1_req1 = 0;
        int mark1_req2 = 0;
        int count_req1 = 0;
        int count_req2 = 0;

        internal void SendRv(string emsg, RVStatus rv)
        {
            string content = rv.RespCommand(emsg + "," + rv.Content);
            Send(content);
        }
        internal void Send(string message)
        {
            if (GlobalParams.PC.Status_Verified.LO) return;
            try
            {
                if (client == null || client.Connected == false) return;
            }
            catch (Exception ex)
            {
                LogUtility.LOG.Error("client send", ex);
            }

            try
            {
                client.Send(message);
                LogUtility.LOG.Info("SEND " + message);
            }
            catch(Exception ex)
			{
                client.Close();
                LogUtility.LOG.Error("SEND " + message, ex);
            }

        }

		private void Client_Closed(string obj)
		{
			LogUtility.LOG.Info(client.Key + " CLOSED");
			server.RemoveClient(obj);
		}



	}
}
